package com.joolun.web.controller.script;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.joolun.common.core.domain.R;
import com.joolun.script.dto.CommentExt;
import com.joolun.script.entity.Comment;
import com.joolun.script.enums.CommonConfigEnum;
import com.joolun.script.service.CommentService;
import com.joolun.script.service.CommonConfigService;
import com.joolun.web.vo.CommentVO;
import com.joolun.weixin.entity.WxUser;
import com.joolun.weixin.service.WxUserService;
import com.joolun.weixin.utils.ThirdSessionHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 留言内容
 *
 * @author 臣服
 * @date 2022-01-12 10:51:45
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/comment")
@Api(value = "comment", tags = "留言内容管理")
public class CommentController {

    private final CommentService commentService;

    private final CommonConfigService commonConfigService;

    private final WxUserService wxUserService;

    /**
     * 分页列表
     *
     * @param page    分页对象
     * @param comment 留言内容
     * @return
     */
    @ApiOperation(value = "分页列表")
    @GetMapping("/page")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(paramType = "query", dataType = "com.baomidou.mybatisplus.extension.plugins.pagination.Page"),
            @ApiImplicitParam(paramType = "query", dataType = "com.joolun.script.entity.Comment"),
            @ApiImplicitParam(paramType = "query", name = "ascs", required = true, value = "升序字段参数 ascs | descs 任选其一或者混用都可，但是要注意顺序会影响排序结果", dataType = "String"),
            @ApiImplicitParam(paramType = "query", name = "descs", required = true, value = "降序字段参数 ascs | descs 任选其一或者混用都可，但是要注意顺序会影响排序结果", dataType = "String")
    }
    )
    public R<Page<CommentVO>> getPage(HttpServletRequest request, Page<Comment> page, Comment comment) {
        String scriptId = comment.getScriptId();
        Assert.hasText(scriptId, "剧本ID不能为空");
        page = commentService.getPage(page, comment);

        Page<CommentVO> voPage = new Page<>();
        voPage.setCurrent(page.getCurrent());
        voPage.setSize(page.getSize());
        voPage.setPages(page.getPages());
        voPage.setTotal(page.getTotal());
        voPage.setOrders(page.orders());

        List<Comment> records = page.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return R.ok(voPage);
        }

        Set<String> userIdList = new HashSet<>();
        List<String> commentIdList = records.stream().map(o -> {
            userIdList.add(o.getUserId());
            return o.getId();
        }).collect(Collectors.toList());

        List<CommentExt> fullCommentExtList = commentService.queryLastByParentId(scriptId, commentIdList, getLastNumber());
        Map<String, List<CommentExt>> commentExtMap = Collections.emptyMap();
        if (!CollectionUtils.isEmpty(fullCommentExtList)) {
            commentExtMap = new HashMap<>();
            for (CommentExt commentExt : fullCommentExtList) {
                List<CommentExt> commentExtList = commentExtMap.get(commentExt.getCommentId());
                if (CollectionUtils.isEmpty(commentExtList)) {
                    commentExtList = new LinkedList<>();
                }
                commentExtList.add(commentExt);
                commentExtMap.put(commentExt.getCommentId(), commentExtList);

                userIdList.add(commentExt.getUserId());

                CommentExt replyComment = commentExt.getReplyComment();
                if (Objects.nonNull(replyComment)) {
                    userIdList.add(replyComment.getUserId());
                }

            }
        }
//        查询用户信息
        Map<String, WxUser> wxUserMap = wxUserService.getWxUserMap(wxUserService.queryWxUserList(userIdList));

        Map<String, List<CommentExt>> finalCommentExtMap = commentExtMap;
        List<CommentVO> voList = records.stream().map(comm -> {
            CommentVO vo = new CommentVO();
            BeanUtils.copyProperties(comm, vo);

            WxUser wxUser = wxUserMap.get(vo.getUserId());
            if (Objects.nonNull(wxUser)) {
                vo.setNickName(wxUser.getNickName());
                vo.setHeadimgUrl(wxUser.getHeadimgUrl());
            }

            List<CommentExt> replyCommentList = finalCommentExtMap.get(vo.getCommentId());
            vo.setReplyList(replyCommentList);
            if (!CollectionUtils.isEmpty(replyCommentList)) {
                replyCommentList.forEach(replyComment -> {
                    WxUser user = wxUserMap.get(replyComment.getUserId());
                    if (Objects.nonNull(user)) {
                        replyComment.setNickName(user.getNickName());
                        replyComment.setHeadimgUrl(user.getHeadimgUrl());
                    }
                    CommentExt innerReplyComment = replyComment.getReplyComment();
                    if (Objects.nonNull(innerReplyComment)) {
                        WxUser innerReplyCommentUser = wxUserMap.get(innerReplyComment.getUserId());
                        if (Objects.nonNull(innerReplyCommentUser)) {
                            innerReplyComment.setNickName(innerReplyCommentUser.getNickName());
                            innerReplyComment.setHeadimgUrl(innerReplyCommentUser.getHeadimgUrl());
                        }
                    }
                });
            }
            return vo;
        }).collect(Collectors.toList());

        voPage.setRecords(voList);
        return R.ok(voPage);
    }

    private Integer getLastNumber() {
        int number = 3;
        try {
            String numberStr = commonConfigService.queryByEnum(CommonConfigEnum.LAST);
            if (StringUtils.isNoneBlank(numberStr)) {
                number = Integer.parseInt(numberStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            number = 3;
        }
        return number;
    }

    /**
     * 留言-回复列表
     *
     * @param id 留言ID
     * @return AjaxResult
     */
    @ApiOperation(value = "留言-回复列表")
    @GetMapping("/{id}")
    public R<CommentVO> getById(@PathVariable("id") String id) {
        Comment comment = commentService.getById(id);
        if (Objects.isNull(comment)) {
            return R.failed("留言不存在");
        }
        CommentVO vo = new CommentVO();
        BeanUtils.copyProperties(comment, vo);
        WxUser commentUser = wxUserService.getById(comment.getUserId());
        if (Objects.nonNull(commentUser)) {
            vo.setNickName(commentUser.getNickName());
            vo.setHeadimgUrl(commentUser.getHeadimgUrl());
        }

        List<CommentExt> fullCommentExtList = commentService.queryLastByParentId(comment.getScriptId(), Collections.singletonList(comment.getId()), null);

        if (!CollectionUtils.isEmpty(fullCommentExtList)) {
            Set<String> userIdList = new HashSet<>();

            fullCommentExtList.forEach(commentExt -> {
                userIdList.add(commentExt.getUserId());
                CommentExt replyComment = commentExt.getReplyComment();
                if (Objects.nonNull(replyComment)) {
                    userIdList.add(replyComment.getUserId());
                }
            });
            Map<String, WxUser> wxUserMap = wxUserService.getWxUserMap(wxUserService.queryWxUserList(userIdList));

            fullCommentExtList.forEach(commentExt -> {
                WxUser wxUser = wxUserMap.get(commentExt.getUserId());
                if (Objects.nonNull(wxUser)) {
                    commentExt.setNickName(wxUser.getNickName());
                    commentExt.setHeadimgUrl(wxUser.getHeadimgUrl());
                }
                CommentExt innerReplyComment = commentExt.getReplyComment();
                if (Objects.nonNull(innerReplyComment)) {
                    WxUser innerReplyCommentUser = wxUserMap.get(innerReplyComment.getUserId());
                    if (Objects.nonNull(innerReplyCommentUser)) {
                        innerReplyComment.setNickName(innerReplyCommentUser.getNickName());
                        innerReplyComment.setHeadimgUrl(innerReplyCommentUser.getHeadimgUrl());
                    }
                }
            });
            vo.setReplyList(fullCommentExtList);
        }
        return R.ok(vo);
    }

    /**
     * 留言内容新增
     *
     * @param comment 留言内容
     * @return R
     */
    @ApiOperation(value = "留言内容新增")
    @PostMapping
    public R<Boolean> save(@RequestBody Comment comment) {
        Assert.hasText(comment.getScriptId(), "文章ID 必填");
        Assert.hasText(comment.getContent(), "留言内容必填");
        Assert.hasText(comment.getCommentId(), "留言内容必填");
        Assert.notNull(comment.getType(), "类型不能为空");

        int type = Math.min(Math.max(comment.getType(), 1), 2);
        if (type == 2) {
            Assert.hasText(comment.getReplyId(), "留言内容必填");
        }

        String userId = ThirdSessionHolder.getThirdSession().getWxUserId();
        comment.setId(null);
        comment.setUserId(userId);
        comment.setCreateTime(LocalDateTime.now());
        return R.ok(commentService.save(comment));
    }

    /**
     * 留言内容修改
     *
     * @param comment 留言内容
     * @return R
     */
    @ApiOperation(value = "留言内容修改")
//    @PutMapping
    public R<Boolean> updateById(@RequestBody Comment comment) {
        return R.ok(commentService.updateById(comment));
    }

    /**
     * 留言内容删除
     *
     * @param id
     * @return R
     */
    @ApiOperation(value = "留言内容删除")
    @DeleteMapping("/{id}")
    public R<?> removeById(@PathVariable String id) {
        String userId = ThirdSessionHolder.getThirdSession().getWxUserId();
        Comment comment = commentService.getById(id);
        if (Objects.isNull(comment)) {
            return R.ok("删除成功");
        }
        synchronized (this) {
            if (Objects.isNull(comment)) {
                return R.ok("删除成功");
            }
            Boolean isAdmin = ThirdSessionHolder.getThirdSession().getIsAdmin();
            if (userId.equals(comment.getUserId()) || isAdmin) {
                return R.ok(commentService.removeById(id));
            }
        }
        return R.ok("已删除");
    }

}
